package com.xuzao.developer.jedis;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

/**
 * @author xuzao
 * @description ${Description}
 * @date 2018/4/28上午10:47
 */
@Configuration
public class RedisConnPool {

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.pool.max-wait}")
    private long maxWaitMillis;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.pool.max-total}")
    private int maxTotal;

    @Value("${spring.redis.sentinel.nodes}")
    private String nodes;

    @Value("${spring.redis.sentinel.master}")
    private String master;

    private static ThreadLocal<Jedis> threadConns = new ThreadLocal<>();

    private static ThreadLocal<Integer> stackIdx = new ThreadLocal<>();


    private JedisSentinelPool redisSentinelJedisPool;
    @Bean
    public JedisSentinelPool redisPoolFactory() {
        Set<String> sentinels = new HashSet<>();
        String[] nodeArray = nodes.split(",");
        for (String item:nodeArray) {
            sentinels.add(item);
        }


        GenericObjectPoolConfig  genericObjectPoolConfig=new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxIdle(maxIdle);
        genericObjectPoolConfig.setMaxWaitMillis(maxWaitMillis);
        genericObjectPoolConfig.setMaxTotal(maxTotal);

        redisSentinelJedisPool = new JedisSentinelPool(master,sentinels,genericObjectPoolConfig,timeout,password);


        return redisSentinelJedisPool;
    }

    /**
     * 从链接池取连接
     *
     * @return
     */
    public Jedis getConnection() {
        Jedis result = threadConns.get();
        if (result == null) {
            result = redisSentinelJedisPool.getResource();
            stackIdx.set(0);
            threadConns.set(result);
        } else {
            Integer intIdx = stackIdx.get();
            stackIdx.set(intIdx + 1);
        }
        return result;
    }

    /**
     * 回收连接
     *
     * @param conn
     */
    public void recycle(Jedis conn) {
        Integer intIdx = stackIdx.get();
        if (intIdx == null) {
            intIdx = 0;
        }
        if (intIdx == 0) {
            threadConns.remove();
            conn.close();
            stackIdx.remove();
        } else {
            stackIdx.set(intIdx - 1);
        }
    }


}
